/*****************************
工程名称：直流有刷电机调速与换向控制
控制模式：
（1）PWM模式：0~100%占空比；频率1KHZ.
（2）POT航模电调模式：脉冲宽度：1~2ms;频率50HZ.
单片机工作频率：11.0592MHZ
单片机机器周期：1T模式
*****************************/
#include <reg52.h>

//sbit MODE=P3^5;//模式引脚，MODE=1:PWM模式。MODE=0：POT模式。
//sbit DR=P3^3;//PWM模式控制引脚
bit DR=1;
//sbit PWM_IN=P3^2;
//外部输入PWM输入引脚，也是外部中断引脚，通过边沿触发模式测量输入的脉宽(POT模式)或者占空比(PWM模式)
sbit PWM_OUT=P3^3;
//IN1单片机输出PWM信号控制电机转速，通过定时器0及其中断，输出占空比等于DC的PWM波
//sbit IN2=P3^0;//IN2通过高低电平控制正转反转

sfr P3M0=0XB2;
sfr P3M1=0XB1;
sfr AUXR=0X8E;//不可以位寻址的-定时器2
sfr INT_CLKO = 0x8f; //唤醒和时钟输出功能寄存器
sfr T2H = 0xD6; //定时器2高八位
sfr T2L = 0xD7;//定时器2低八位

int DC=0;//定义占空比的变量,赋初值
int time=1;
float WIDE1=1.2,WIDE2=1.2,WIDE=0;//WIDE1正周期，WIDE2负周期，WIDE脉宽/占空比
float DUTY1=0.2,DUTY2=0.5;
bit FLAGZHENG=0;//MODE=1:PWM模式。MODE=0：POT模式
bit MODE=0;//MODE=1:PWM模式。MODE=0：POT模式
bit Flag1=0,Flag0=0;


void timer0_ini()  //定时器0初始化函数
{
	AUXR |= 0x80;		//定时器0时钟1T模式
	TMOD &= 0xF0;		//设置定时器0模式-16位重装模式
	TL0 = 0x91;		//设置定时器0初值/重装值-低八位-10微妙定时
	TH0 = 0xFF;		//设置定时器0初值/重装值-高八位-10微妙定时
	EA=1;//开总中断
  ET0=1;//开定时器0中断
	TR0=1;//启动定时器0
}

void timer2_ini()  //定时器2初始化函数
{
	AUXR |= 0x04;  //定时器2设置为1T工作模式
	T2L = 0x00;		//设置定时器2初值-低八位
	T2H = 0x00;		//设置定时器2初值-低八位
}

void timer0() interrupt 1 //定时器0中断函数-用于输出占空比为DC的PWM波到P3.1 
{ 
	time++;
	if(time>100)
	{ 
		time=1;
	}
	if(1<=time && time<=DC)   //DC=占空比%
	{
		PWM_OUT=1;
	}
	if(DC<time && time<=100 )
	{
		PWM_OUT=0;
	}
}

void 	int0_ini() //中断0初始化函数
{
	EX0=1;//使能中断0
	IT0=0;//边沿触发模式
	EA=1;//开启中断
}
void INT0_int() interrupt 0
{
	bit FLAG;
	FLAG=INT0;//保存INT0的状态，1为上升沿，0为下降沿
	if(MODE)//MODE=1,PWM模式
	{
		if (FLAGZHENG)//
		{
			if(FLAG)
			{
				AUXR &=~(1<<4);//定时器2停止计时
				T2H=0x00;//设置定时器2初值
				T2L=0x00;//设置定时器2初值
				AUXR |= 0x10; //定时器2开始计时
			}
			else 
			{
				AUXR &=~(1<<4);//定时器2停止计时
				WIDE1=(float)(T2L+T2H*256);//计算正周期	
				FLAGZHENG =!FLAGZHENG;	
				T2H=0x00;//设置定时器2初值
				T2L=0x00;//设置定时器2初值
				AUXR |= 0x10; //定时器2开始计时
			}
		}
		else 
		{
				AUXR &=~(1<<4);//定时器2停止计时
				WIDE2=(float)(T2L+T2H*256);//计算负周期	
				FLAGZHENG =!FLAGZHENG;	
				T2H=0x00;//设置定时器2初值
				T2L=0x00;//设置定时器2初值
				AUXR |= 0x10; //定时器2开始计时
		}		
   Flag1=!Flag0;		
  }
  else //MODE=0,POT模式	
	{
		if (FLAG)//上升沿
		{
			AUXR &=~(1<<4);//定时器2停止计时
			T2H=0x00;//设置定时器2初值
			T2L=0x00;//设置定时器2初值
			AUXR |= 0x10; //定时器2开始计时
		}
		else
		{
			AUXR &=~(1<<4);//定时器2停止计时
			WIDE=(float)(T2L+T2H*256);//计算正周期
      Flag1=!Flag0;
	  }
  }
}
void PWM_MODE() //MODE=1,PWM模式
{
	while(1)
	{
		if(Flag1 != Flag0)
		{
				DUTY1=WIDE1*9/100000;//单位毫秒。震荡一次时间为0.09us=1/11.0592.
				DUTY2=WIDE2*9/100000;//单位毫秒。震荡一次时间为0.09us=1/11.0592.
				WIDE=DUTY1/(DUTY1+DUTY2);//计算占空比
				Flag1=Flag0;
		}
		DC=(int)(WIDE*100);
		if (!DC) //占空比为0，停转：IN1=0，IN2=0;
		{	
			ET0=0;//关闭定时器0中断
//			IN2=0;
		  PWM_OUT=0;//IN1=0;
		}	
		if (!DR)//DR=0低电平反转：PWM_OUT=P3^1，IN1/P3.1/PWM_OUT, IN2/P3.0=1;
		{
				ET0=1;//打开定时器0中断
//			IN2=1;//IN2/P3.0=1;
		}
		if (DR) //DR=1高电平正转，IN1/P3.1=PWM_OUT, IN2/P3.2=0
		{
			ET0=1;//打开定时器0中断
//		IN2=0;//IN2/P3.0=0;
	  }		
	}
}
void POT_MODE() //MODE=0,POT模式
{
	while(1)
	{
		if(Flag1 != Flag0)
		{
			WIDE=WIDE*9/100000;//单位毫秒。震荡一次时间为0.09us=1/11.0592
			if(1<=WIDE&&WIDE<1.45)	//脉宽1~1.45ms,电机正转：IN1/P3.1/PWM_OUT, IN2/P3.2=0		
			{
				WIDE=1-(WIDE-1)/0.45;
				DC=(int)(WIDE*100);
				Flag1=Flag0;
				ET0=1;//开定时器0中断
//			IN2=0;//IN2/P3.0=0;
			}
			if(1.55<WIDE&&WIDE<=2)//脉宽1.55~2ms,电机反转：IN1/P3.1/PWM_OUT, IN2/P3.0=1		
			{
				WIDE=(WIDE-1.55)/0.45;
				DC=(int)(WIDE*100);
				Flag1=Flag0;
				ET0=1;//开定时器0中断
//			IN2=1;//IN2/P3.0=1;
			}
			if(1.45<=WIDE&&WIDE<=1.55)	//停转：IN1=0，IN2=0;
			{	
				ET0=0;//关闭定时器0中断
//		  IN2=0;
				PWM_OUT=0;//IN1=0;
			}
	  }
  }
}

void main()
{
	PX0=1;
	timer0_ini();
	timer2_ini();
  int0_ini();
	if(MODE)
	{
  PWM_MODE();
	}
	else
	{
	POT_MODE();
	}
}
